#ifndef SYSTEM_MONITOR_H
#define SYSTEM_MONITOR_H

#include <sigc++/signal.h>
#include <sigc++/connection.h>

#include <glibtop.h>
#include <sys/types.h>

#include <unordered_set>
#include <unordered_map>
#include <utility>
#include <memory>
using std::auto_ptr;
using std::pair;

class configuration;
class process_t;

class system_monitor {
public:
    explicit system_monitor (const configuration&);
    ~system_monitor ();

    /* this function will be called routinely to monitor system loads */
    bool check_system_loads ();

    /* signal type */
    typedef sigc::signal<void, const process_t&> process_signal_add_t;
    typedef sigc::signal<void, pid_t> process_signal_rm_t;

    /* signals */
    process_signal_add_t signal_add_process;
    process_signal_add_t signal_update_process;
    process_signal_rm_t signal_remove_process;
    process_signal_add_t signal_sys_update; /* reports system health */

private:
    /* sturct that sotore process's cpu time and other information */
    struct process_data_t{
        guint64 cpu_time;
        guint64 cpu_total_time;
        double read_bytes;
        double write_bytes;
        time_t io_time_last;
    };

    /* last total cpu time */
    guint64 cpu_total_time_last_;
    guint64 cpu_used_time_last_;

    /* last io bytes */
    long read_bytes_last_;
    long write_bytes_last_;

    /* nubmer of cpu */
    guint64 ncpu_;

    /* configuration file */
    const configuration &original_config_;

    /* temporary configuration */
    /* because the config may be changed by appmenu_updater anytime,
     * so we should store a const copy in case of errors. */
    auto_ptr<configuration> config_; 

    /* last time check all processes */
    time_t last_check_time_;
    time_t now_time_;

    /* store the connection with timeout signal */
    sigc::connection timeout_connection_;

    /* store all processes's information */
    typedef std::unordered_map<pid_t, process_data_t> process_list_t;
    process_list_t process_list_;

	/* store processes been warned */
    typedef std::unordered_set<pid_t> process_store_t;
    process_store_t warned_processes_;
    process_store_t unchecked_list_;

private:
    /* utils */
    float get_sys_cpu_usage ();
    long  get_sys_mem ();
    void  get_sys_io (long*, long*);
    void  get_process_io (const char*, long long*, long long*);

    /* process examination steps */
    void go_through_process ();
    void go_through_bad_process (); /* check only noisy processes */
    bool check_single_process (pid_t);
    void send_signal_add (const process_t&);
    void send_signal_rm (pid_t);
    void clean_invalid_process ();
};

#endif /* end of SYSTEM_MONITOR_H */

